<#include "/templates/xjj-index.ftl">
<#include "/templates/xjj-list.ftl">
<@navList navs=navArr/>
<@content id=tabId>
    <@query>
        <input type="hidden" id="workplatform-className">
        <input type="hidden" id="workplatform-classLoaderHash">
        <input type="hidden" id="workplatform-method">

        <@querygroup title='类名'>
            <input type="text" id="workplatform_classname" value="*Controller" class="form-control input-sm"
                   placeholder="支持模查询">
        </@querygroup>
        <@button type="info" icon="glyphicon glyphicon-plus" onclick="searchClass()">查询</@button>
    </@query>
</@content>

<@list showPage=false>
    <thead>
    <tr>
        <th>方法列表</th>
        <th>类名</th>
        <th>装载器</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody id="classList">
    </tbody>
</@list>

<script type="text/javascript">
    //类序列号
    var classNum = 0;
    //参数
    var classInfo = "";
    //类装载器
    var classLoaderHash = "";
    //显示method
    var classMethodNum = 0;

    searchClass();

    //查询类列表
    function searchClass() {
        var workplatform_ip = '${meteor_param.arthasIp}';
        var workplatform_port = '${meteor_param.arthasPort}';
        var workplatform_agentId = '${meteor_param.arthasAgentId}';
        var workplatform_classname = $("#workplatform_classname").val();
        if (workplatform_ip == '') {
            XJJ.msger('机器IP不能为空,请在[meteor]-[全局参数设置]中进行配置');
            return;
        }
        if (workplatform_port == '') {
            XJJ.msger('端口号不能为空');
            return;
        }
        if (workplatform_agentId == '') {
            workplatform_agentId = "null";
        }
        if (workplatform_classname == '' || workplatform_agentId == undefined) {
            XJJ.msger('类名不能为空');
            return;
        }
        $("#classList").html("");
        classNum = 0;
        classInfo = "";
        classLoaderHash = "";
        var cmd = "sc -d " + workplatform_classname;
        getReturnInfo(workplatform_ip, workplatform_port, workplatform_agentId, cmd, buildClassList);
    }

    //构建class tabel
    function buildClassList(data) {
        var param = "";
        var addDom = false;
        if (data != null && data != "") {
            if (data == true) {
                return;
            }
            data = data.trim();
            if (data.startWith("class-info") || data.startWith("classLoaderHash")) {
                param = data.split(/\s+/);
                if (param != null && param.length > 0) {
                    if (param[0] == "class-info") {
                        classInfo = param[1]
                    } else if (param[0] == "classLoaderHash") {
                        addDom = true;
                        classNum = classNum + 1;
                        if (param.length == 2) {
                            classLoaderHash = param[1];
                        } else {
                            classLoaderHash = "";
                        }
                    }
                }
            }

        }

        if (!addDom) {
            return;
        }
        $("#classList").append("<tr>\n" +
            "<td class='center'>\n" +
            "<div class='action-buttons'>\n" +
            "<a href='#' class='green bigger-140 show-details-btn' onclick='showMethod(this,\"" + classInfo + "\",\"" + classNum + "\")' title='查看方法列表'>\n" +
            "<i class='ace-icon fa fa-angle-double-down'></i>\n" +
            "<span class='sr-only'>详细</span>\n" +
            "</a>\n" +
            "</div>\n" +
            "</td>\n" +
            "<td>" + classInfo + "</td>\n" +
            "<td>" + classLoaderHash + "</td>\n" +
            "<td>\n" +
            "<button type='button' class='btn btn-info btn-xs' onclick='classDetail(\"" + classInfo + "\",\"" + classLoaderHash + "\")'>详细</button>\n" +
            "<button type='button' class='btn btn-info btn-xs' onclick='javaCode(\"" + classInfo + "\",\"" + classLoaderHash + "\")'>查看源码</button>\n" +
            "<button type='button' class='btn btn-info btn-xs' onclick='downLoadSource(\"" + classInfo + "\",\"" + classLoaderHash + "\")'>下载源码</button>\n" +
            "</td>\n" +
            "</tr>\n");
        $("#classList").append("<tr class='detail-row'>\n" +
            "    <td colspan='8'>\n" +
            "        <div class='table-detail'>\n" +
            "            <div class='row'>\n" +
            "                <table class='table table-bordered'>\n" +
            "                    <thead>\n" +
            "                    <tr>\n" +
            "                        <th>方法</th>\n" +
            "                        <th>简写</th>\n" +
            "                        <th>操作</th>\n" +
            "                    </tr>\n" +
            "                    </thead>\n" +
            "                    <tbody id='class-" + classNum + "' classname='" + classInfo + "' classloaderhash='" + classLoaderHash + "'>\n" +
            "                    </tbody>\n" +
            "                </table>\n" +
            "            </div>\n" +
            "        </div>\n" +
            "    </td>\n" +
            "</tr>");
    }

    //查询 method
    function showMethod(dom, classname, num) {
        if (!$(dom).closest('tr').next().hasClass("open")) {
            //发送
            classMethodNum = num;
            var workplatform_ip = '${meteor_param.arthasIp}';
            var workplatform_port = '${meteor_param.arthasPort}';
            var workplatform_agentId = '${meteor_param.arthasAgentId}';
            var workplatform_classname = classname;
            if (workplatform_ip == '') {
                XJJ.msger('机器IP不能为空');
                return;
            }
            if (workplatform_port == '') {
                XJJ.msger('端口号不能为空');
                return;
            }
            if (workplatform_agentId == '') {
                workplatform_agentId = "null";
            }
            if (workplatform_classname == '' || workplatform_agentId == undefined) {
                XJJ.msger('类名不能为空');
                return;
            }

            $("#class-" + classNum).html("");
            var cmd = "sm " + workplatform_classname;
            getReturnInfo(workplatform_ip, workplatform_port, workplatform_agentId, cmd, buildMethodList);
        }


        $(dom).closest('tr').next().toggleClass('open');
        $(dom).find(ace.vars['.icon']).toggleClass('fa-angle-double-down').toggleClass('fa-angle-double-up');
    }

    //构建method table
    function buildMethodList(data) {
        var method = "";
        if (data != undefined && data != null && data != "") {
            if (data == true) {
                return;
            }
            method = data;
            method = method.split(" ")[1];
            method = method.substr(0, method.indexOf("("));
        }
        var className = $("#class-" + classMethodNum).attr("classname");
        $("#class-" + classMethodNum).append("<tr>\n" +
            "<td>" + data + "</td>\n" +
            "<td>" + method + "</td>\n" +
            "<td>\n" +
            "<button type='button' style='margin-top: 5px' class='btn btn-info btn-xs' onclick='methodDetail(\"" + className + "\",\"" + method + "\")'>详细</button>\n" +
            "<button type='button' style='margin-top: 5px' class='btn btn-info btn-xs' onclick='monitor(\"" + className + "\",\"" + method + "\")'>调用次数监控</button>\n" +
            "<button type='button' style='margin-top: 5px' class='btn btn-info btn-xs' onclick='trace(\"" + className + "\",\"" + method + "\")'>调用链监控</button>\n" +
            "<button type='button' style='margin-top: 5px' class='btn btn-info btn-xs' onclick='stack(\"" + className + "\",\"" + method + "\")'>被调用链监控</button>\n" +
            "<button type='button' style='margin-top: 5px' class='btn btn-info btn-xs' onclick='watch(\"" + className + "\",\"" + method + "\")'>查看调用信息</button>\n" +
            "<button type='button' style='margin-top: 5px' class='btn btn-info btn-xs' onclick='timetunnel(\"" + className + "\",\"" + method + "\")'>时光隧道</button>\n" +
            "</td>\n" +
            "</tr>");
    }

    //类详细
    function classDetail(data, classLoaderHash) {
        var cmd = "sc -d -f " + data;
        if (classLoaderHash != null && classLoaderHash.trim() != "") {
            cmd = "sc -c " + classLoaderHash + " -d -f " + data;
        }
        sendCmd(cmd);
        $("#XjjTab li a[href='#meteor_arthas']").trigger("click");
    }

    //反编译
    function javaCode(data, classLoaderHash) {
        //生成源码文件
        var workplatform_ip = '${meteor_param.arthasIp}';
        var workplatform_port = '${meteor_param.arthasPort}';
        var workplatform_agentId = '${meteor_param.arthasAgentId}';
        if (workplatform_ip == '') {
            XJJ.msger('机器IP不能为空');
            return;
        }
        if (workplatform_port == '') {
            XJJ.msger('端口号不能为空');
            return;
        }

        $("#workplatform-className").val(data);
        $("#workplatform-classLoaderHash").val(classLoaderHash);
        //跳转到javacode
        XJJ.showTab({id: 'meteor_javacode', text: '查看源码', url: '/meteor/javacode/index', navs: 'meteor,查看源码'});
        //执行代码
        setTimeout(function () {
            getJavaCode();
        }, 1000);
    }

    //下载源码
    function downLoadSource(data, classLoaderHash) {
        //生成源码文件
        var names = data.split(".");
        names = names[names.length - 1];
        var cmd = "jad --source-only " + data + " > /tmp/meteor/" + names + ".java";
        if (classLoaderHash != null && classLoaderHash.trim() != "") {
            cmd = "jad  -c " + classLoaderHash + " --source-only " + data + " > /tmp/meteor/" + names + ".java";
        }
        sendCmd(cmd);
        XJJ.msgok("请稍后，5秒后将下载源码");
        setTimeout(function () {
            //下载源码文件
            window.location.href = '${base}/meteor/javacode/download/' + names;
        }, 5000)

    }

    //方法详细
    function methodDetail(className, method) {
        var cmd = "sm -d " + className + " " + method;
        sendCmd(cmd);
        $("#XjjTab li a[href='#meteor_arthas']").trigger("click");
    }

    //监控
    function monitor(className, method) {
        $("#workplatform-className").val(className);
        $("#workplatform-method").val(method);
        XJJ.msgok("每5秒获取1次监控数据，ctr+c退出监控");
        XJJ.showTab({id: 'meteor_monitor', text: '方法调用监控', url: '/meteor/monitor/index', navs: 'meteor,方法监控'});
        //执行代码
        setTimeout(function () {
            sendMonitorCmd(className, method);
        }, 500);
    }

    //方法执行链路
    function trace(className, method) {
        $("#workplatform-className").val(className);
        $("#workplatform-method").val(method);
        XJJ.msgok("过滤掉了掉了jdk函数，ctr+c退出监控");
        XJJ.showTab({id: 'meteor_trace', text: '调用链监控', url: '/meteor/trace/index', navs: 'meteor,方法监控'});
        setTimeout(function () {
            sendTraceCmd(className, method);
        }, 500);
    }

    //被调用的链路
    function stack(className, method) {
        $("#workplatform-className").val(className);
        $("#workplatform-method").val(method);
        XJJ.msgok("查询该方法被调用的链路，ctr+c退出监控");
        XJJ.showTab({id: 'meteor_stack', text: '被调用链监控', url: '/meteor/stack/index', navs: 'meteor,方法监控'});
        setTimeout(function () {
            sendStackCmd(className, method);
        }, 500);
    }

    //时光隧道
    function timetunnel(className, method) {
        $("#workplatform-className").val(className);
        $("#workplatform-method").val(method);
        XJJ.msgok("记录方法被调用现场，ctrl+c退出监控");
        XJJ.showTab({id: 'meteor_timetunnel', text: '记录调用现场', url: '/meteor/timetunnel/index', navs: 'meteor,时光隧道'});
        setTimeout(function () {
            sendTimetunnelCmd(className, method);
        }, 500);
    }

    //watch
    function watch(className, method) {
        $("#workplatform-className").val(className);
        $("#workplatform-method").val(method);
        XJJ.msgok("记录方法被调用现场，ctrl+c退出监控");
        XJJ.showTab({id: 'meteor_watch', text: '查看方法请求与返回', url: '/meteor/watch/index', navs: 'meteor,watch'});
        setTimeout(function () {
            sendWatchCmd(className, method);
        }, 500);
    }


</script>

